import java.io.*;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Calendar;
import java.text.SimpleDateFormat;

public class RinexGLONASSNavFile {
    
    private String fileName;

    private static String versionStr     = "RINEX VERSION / TYPE";
    private static String programStr     = "PGM / RUN BY / DATE";
    private static String commentStr     = "COMMENT";
    private static String ionoCorrStr    = "IONOSPHERIC CORR";
    private static String timeCorrStr    = "TIME SYSTEM CORR";
    private static String leapSecondsStr = "LEAP SECONDS";
    private static String eohStr         = "END OF HEADER";
    
    // Need to add in TIME SYSTEM CORR
    private int eohFlag = 0;
    private int records = 0;
    private int lineCtr = 0;

    //private static Pattern pStartRecord = Pattern.compile("^\\s+\\d+\\s+\\d+\\s+\\d+");
    private static Pattern pStartRecord = Pattern.compile("^?\\s+\\d+\\s+\\d+\\s+");
    private static StringUtils util;

    private NavDataGlonass[] gDataArray;

    RinexGLONASSNavFile(String filename) {
        fileName = filename;
    }

    public void readGLONASSNavFile() {
        try {
            File file = new File(fileName);
            FileReader reader = new FileReader(file);
            BufferedReader in = new BufferedReader(reader);
            String line;
            //
            // Do a first pass to work out how many record there are
            //
            while ( (line = in.readLine()) != null) {
                if(eohFlag == 0 && line.length() > 60) {
                    String endOfLine = line.substring(60);
                    if( eohStr.matches(endOfLine) ) {
                        System.out.println("Found the end of Header marker");
                        eohFlag = 1;
                    }
                }
                else if(eohFlag == 1) {
                    Matcher m = pStartRecord.matcher(line);
                    if(m.find()) {
                        records++;
                        // _parseStartRecord(line);
                    }
                    //else {
                        // _parseGLONASSNavLine(line);
                    //}
                }
            }
            in.close();
            System.out.println("Total Number of GLONASS Nav Records:"+records);

            //
            // Now try and Parse the GLONASS Navigation file into a data structure
            //
            eohFlag = 0;
            reader = new FileReader(file);
            in = new BufferedReader(reader);

            gDataArray = new NavDataGlonass[records];
            records = 0;
            while ( (line = in.readLine()) != null) {
                if(eohFlag == 0 && line.length() > 60) {
                    String endOfLine = line.substring(60);
                    if( eohStr.matches(endOfLine) ) {
                        //System.out.println("Found the end of Header marker");
                        eohFlag = 1;
                    }
                }
                else if(eohFlag == 1) {
                    Matcher m = pStartRecord.matcher(line);
                    if( m.find() ) {
                        //System.out.println("Found a new record "+line);
                        _parseStartRecord(line);
                    }
                    else {
                        //System.out.println("Parsing data");
                        _parseGLONASSNavLine(line);
                    }
                }
            }
            in.close();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }

    private void _parseStartRecord(String line) {
        Integer prn = Integer.parseInt( util.lrtrim( line.substring(0,2) ) );
        //System.out.print("PRN:"+prn+": ");

        Integer YY = Integer.parseInt( util.lrtrim( line.substring(3,5) ) );
        //System.out.print("YY:"+YY+": ");
        Integer MM = Integer.parseInt( util.lrtrim( line.substring(6,8) ) );
        //System.out.print("MM:"+MM+": ");
        Integer DD = Integer.parseInt( util.lrtrim( line.substring(9,11) ) );
        //System.out.print("DD:"+DD+": ");
        Integer hh = Integer.parseInt( util.lrtrim( line.substring(12,14) ) );
        //System.out.print("hh:"+hh+": ");
        Integer mm = Integer.parseInt( util.lrtrim( line.substring(15,17) ) );
        //System.out.print("mm:"+mm+": ");
        Integer ss = Integer.parseInt( util.lrtrim( line.substring(18,20) ) );
        //System.out.print("ss:"+ss+": ");
        Integer ms = Integer.parseInt( util.lrtrim( line.substring(21,22) ) );
        //System.out.print("ms:"+ms+": ");

        //System.out.println();
        Calendar cal = Calendar.getInstance();
        int year;
        if( YY < 80 ) { year = YY + 2000; }
        else { year = YY + 1900; }

        cal.set(Calendar.YEAR,year);
        cal.set(Calendar.MONTH,MM);
        cal.set(Calendar.DAY_OF_MONTH,DD);
        cal.set(Calendar.HOUR_OF_DAY,hh);
        cal.set(Calendar.MINUTE,mm);
        cal.set(Calendar.SECOND,ss);
        cal.set(Calendar.MILLISECOND,ms);
        long timeInMillis = cal.getTimeInMillis();
        double time = timeInMillis / 1000.0;
        NavDataGlonass gData = new NavDataGlonass(prn,time);
        gDataArray[records] = gData;

        Double clockBias = Double.parseDouble(util.lrtrim(line.substring(22,41)).replace('D','E'));
        gDataArray[records].setClockBias(clockBias);
        //System.out.print("clockBias:"+clockBias+": ");
        Double relativeFreqBias = Double.parseDouble(util.lrtrim(line.substring(41,60).replace('D','E')));
        gDataArray[records].setRelativeFreqBias( relativeFreqBias );
        //System.out.print("relativeFreqBias:"+relativeFreqBias+": ");
        Double messageFrameTime = Double.parseDouble(util.lrtrim(line.substring(60,79)).replace('D','E'));
        gDataArray[records].setMessageFrameTime( messageFrameTime );
        //System.out.print("messageFrameTime:"+messageFrameTime+": ");

        //System.out.println();
        lineCtr=1;
    }

    private void _parseGLONASSNavLine(String line) {
        //System.out.println("LINE:"+line);
        String r1 = util.lrtrim( line.substring(3,22) ).replace('D','E');
        String r2 = util.lrtrim( line.substring(22,41) ).replace('D','E');
        String r3 = util.lrtrim( line.substring(41,60) ).replace('D','E');
        String r4 = util.lrtrim( line.substring(60,79) ).replace('D','E') ;

        if(lineCtr == 1) {
            gDataArray[records].setSatX(Double.parseDouble( r1 ) ); // km
            gDataArray[records].setVelX(Double.parseDouble( r2 ) ); // km/sec
            gDataArray[records].setAccX(Double.parseDouble( r3 ) ); // km/sec2
            gDataArray[records].setHealth(Double.parseDouble( r4 ) ); // 0 = OK
        }
        else if(lineCtr == 2) {
            gDataArray[records].setSatY(Double.parseDouble( r1 ) );  
            gDataArray[records].setVelY(Double.parseDouble( r2 ) );
            gDataArray[records].setAccY(Double.parseDouble( r3 ) );
            gDataArray[records].setFreqNo(Double.parseDouble( r4 ) ); // -7 .. +13
        }
        else if(lineCtr == 3) {
            gDataArray[records].setSatZ(Double.parseDouble( r1 ) );
            gDataArray[records].setVelZ(Double.parseDouble( r2 ) );
            gDataArray[records].setAccZ(Double.parseDouble( r3 ) );
            gDataArray[records].setAgeOfOp(Double.parseDouble( r4 ) ); // (days) (E)
            records++;
        }
        //System.out.println();
    }
   
}



